using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace UdpServerTest
{
    public class ByteHelper
    {
        /// <summary>
        /// 16进制转byte
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static byte[] HexStringToByteArray(string s)
        {
            if (s.Length == 0)
            {
                throw new Exception("将16进制字符串转换成字节数组时出错，错误信息：被转换的字符串长度为0。");
            }
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }
        /// <summary>
        /// byte转16进制
        /// </summary>
        /// <param name="buf"></param>
        /// <returns></returns>
        public static string ByteArrayToHexString(byte[] buf)
        {
            List<string> str = new List<string>();
            for (int index = 0; index < buf.Length; index++)
            {
                str.Add(((int)buf[index]).ToString("X2"));
            }
            return string.Join(" ", str.ToArray());
        }

        /// <summary>
        /// 文件转byte[] 
        /// </summary>
        /// <param name="fileUrl"></param>
        /// <returns></returns>
        public static byte[] GetFileData(string fileUrl)
        {
            FileStream fs = new FileStream(fileUrl, FileMode.Open, FileAccess.Read);
            try
            {
                byte[] buffur = new byte[fs.Length];
                fs.Read(buffur, 0, (int)fs.Length);

                return buffur;
            }
            catch (Exception ex)
            {
                //MessageBoxHelper.ShowPrompt(ex.Message);
                return null;
            }
            finally
            {
                if (fs != null)
                {

                    //关闭资源
                    fs.Close();
                }
            }
        }

        /// <summary>
        /// 汉字转GB2312 16进制
        /// </summary>
        /// <param name="TheString"></param>
        /// <returns></returns>
        public static byte[] SinogramToGB2312Bytes(string TheString)
        {
            Encoding FromEcoding = Encoding.GetEncoding("UTF-8");
            Encoding ToEcoding = Encoding.GetEncoding("GB2312");
            byte[] FromBytes = FromEcoding.GetBytes(TheString);
            byte[] ToBytes = Encoding.Convert(FromEcoding, ToEcoding, FromBytes);
            return ToBytes;
        }

        /// <summary>
        /// byte高位在前，低位在后
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="startAddress"></param>
        /// <returns></returns>
        public static Dictionary<int, byte[]> ByteAddress(byte[] bytes, int startAddress = 0)
        {
            Dictionary<int, byte[]> dic = new Dictionary<int, byte[]>();
            for (int i = 0; i + 1 < bytes.Length; i = i + 2)
            {
                dic.Add(startAddress, new[] { bytes[i], bytes[i + 1] });
                startAddress++;
            }

            return dic;
        }

        /// <summary>
        ///  获取crc校验字节
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte[] GetModbusCrc16(byte[] bytes)
        {
            byte crcRegister_H = 0xFF, crcRegister_L = 0xFF;// 预置一个值为 0xFFFF 的 16 位寄存器

            byte polynomialCode_H = 0xA0, polynomialCode_L = 0x01;// 多项式码 0xA001

            for (int i = 0; i < bytes.Length; i++)
            {
                crcRegister_L = (byte)(crcRegister_L ^ bytes[i]);

                for (int j = 0; j < 8; j++)
                {
                    byte tempCRC_H = crcRegister_H;
                    byte tempCRC_L = crcRegister_L;

                    crcRegister_H = (byte)(crcRegister_H >> 1);
                    crcRegister_L = (byte)(crcRegister_L >> 1);
                    // 高位右移前最后 1 位应该是低位右移后的第 1 位：如果高位最后一位为 1 则低位右移后前面补 1
                    if ((tempCRC_H & 0x01) == 0x01)
                    {
                        crcRegister_L = (byte)(crcRegister_L | 0x80);
                    }

                    if ((tempCRC_L & 0x01) == 0x01)
                    {
                        crcRegister_H = (byte)(crcRegister_H ^ polynomialCode_H);
                        crcRegister_L = (byte)(crcRegister_L ^ polynomialCode_L);
                    }
                }
            }



            return new byte[] { crcRegister_L, crcRegister_H };
        }

        /// <summary>
        /// 末尾添加crc16 校验
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte[] AddModbusCrc16(byte[] bytes)
        {
            var crc = GetModbusCrc16(bytes);
            var list = bytes.ToList();
            list.AddRange(crc);
            return list.ToArray();
        }

        /// <summary>
        /// crc16校验
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static bool CheckMobusCrc16(byte[] bytes)
        {
            if (bytes.Length < 3)
            {
                return false;
            }
            var ncheck = bytes.Take(bytes.Length - 2);

            var cmp = bytes.Skip(bytes.Length - 2).Take(2).ToArray();
            var cmp2 = GetModbusCrc16(ncheck.ToArray());
            if (cmp[0] == cmp2[0] && cmp[1] == cmp2[1])
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取32位整数
        /// </summary>
        /// <param name="highH"></param>
        /// <param name="highL"></param>
        /// <param name="lowH"></param>
        /// <param name="lowL"></param>
        /// <returns></returns>
        public static int GetInt(byte highH, byte highL, byte lowH, byte lowL)
        {
            return (highH * 256 + highL) * 256 + lowH * 256 + lowL;
        }

        /// <summary>
        /// 累加和校验值
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte DoSumCheck(byte[] data)
        {
            byte cs = 0;
            for (int i = 0; i < data.Length; i++)
            {
                cs = (byte)((cs + data[i]) % 256);
            }
            return cs;
        }
        /// <summary>
        /// 累加和校验 检查
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool CheckDoSum(byte[] data)
        {
            byte sum = DoSumCheck(data.Take(data.Length - 1).ToArray());
            return data.Last() == sum;
        }


    }
}
